package gdconf

import "C"
import (
	"math/rand"
	"server_cluster/common/logger"
	"server_cluster/common/tools"
	"strconv"
	"strings"
)

const (
	REWARD_TYPE_ALL         = 0 // 全部获得
	REWARD_TYPE_RAND        = 1 // 随机
	REWARD_TYPE_OPTION      = 2 // 自选
	REWARD_TYPE_ROLE_PIECES = 3 // 角色碎片
)

type RewardConfig4Db struct {
	Id       int32           `csv:"ID" gorm:"primary_key;autoIncrement:false"` // 奖励id
	TypeNum  string          `csv:"Type_num,omitempty"`                        // 奖励类型
	ItemList IdNumWeightList `csv:"Item_list,omitempty"`                       // 奖励物品列表
	Exp      int32           `csv:"Exp,omitempty"`
}

func (r *RewardConfig4Db) TableName() string { return "config_reward" }
func (g *GameDataConfig) saveReward() {
	saveTableToDb[RewardConfig4Db](g.Db, readTable[RewardConfig4Db](g.CsvPathPrefix+"Reward.csv"))
}

type RewardConfig struct {
	Id        int32
	Type      int8
	Num       int32
	ItemList  IdNumWeightList
	EXP       int32
	RandomNum int32
}

func (g *GameDataConfig) loadRewardConfig() {
	g.GameDataMaps.RewardMap = make(map[int32]*RewardConfig)
	for _, reward := range loadTableFromDb[RewardConfig4Db](g.Db) {
		var rewardConfig = RewardConfig{}
		rewardConfig.Id = reward.Id
		rewardConfig.ItemList = reward.ItemList
		rewardConfig.EXP = reward.Exp

		if reward.TypeNum != "" {
			list := strings.Split(reward.TypeNum, ";")
			length := len(list)
			if length < 1 || length > 3 {
				panic("config_reward table format error")
			}
			var num, err = strconv.Atoi(list[0])
			if err != nil {
				panic(err)
			}
			rewardConfig.Type = int8(num)
			if length == 2 {
				num, err = strconv.Atoi(list[1])
				if err != nil {
					panic(err)
				}
				rewardConfig.Num = int32(num)
			}
			if length == 3 {
				num, err = strconv.Atoi(list[1])
				if err != nil {
					panic(err)
				}
				rewardConfig.Num = int32(num)
				num, err = strconv.Atoi(list[2])
				if err != nil {
					panic(err)
				}
				rewardConfig.RandomNum = int32(num)
			}
		}
		g.GameDataMaps.RewardMap[reward.Id] = &rewardConfig
	}
	logger.Info("RewardConfig Count: %v", len(g.GameDataMaps.RewardMap))
}

func GetConfigReward(id int32) *RewardConfig {
	data, ok := CONF.GameDataMaps.RewardMap[id]
	if !ok {
		return nil
	}
	return data
}

func (r *RewardConfig) GetRewards(times int32, rewards_want, roleList []int32) map[int32]int32 {
	rewards := make(map[int32]int32, 1)
	var itemListLen = len(r.ItemList)
	switch r.Type {
	case REWARD_TYPE_ALL:
		for i := 0; i < itemListLen; i++ {
			if r.ItemList[i].Id > 0 {
				rewards[r.ItemList[i].Id] = r.ItemList[i].Num * times
			}
		}
	case REWARD_TYPE_RAND:
		var i, j int32
		maxV := 0
		val := 0
		for i = 0; i < int32(itemListLen); i++ {
			if r.ItemList[i].Id > 0 {
				maxV += int(r.ItemList[i].Weight)
			} else {
				break
			}
		}
		if maxV == 0 || maxV < int(r.Num) {
			return nil
		}
		times *= r.Num
		for i = 0; i < times; i++ {
			val = rand.Intn(maxV)
			for j = 0; j < int32(itemListLen); j++ {
				if val <= int(r.ItemList[j].Weight) {
					_, ok := rewards[r.ItemList[j].Id]
					if !ok {
						rewards[r.ItemList[j].Id] = 0
					}
					rewards[r.ItemList[j].Id] += r.ItemList[j].Num
					break
				}
				val -= int(r.ItemList[j].Weight)
			}
		}
	case REWARD_TYPE_OPTION:
		if len(rewards_want) != int(r.Num) {
			return nil
		}
		var i, j int32
		for i = 0; i < r.Num; i++ {
			if rewards_want[i] <= 0 {
				return nil
			}
			for j = 0; j < int32(itemListLen); j++ {
				if rewards_want[i] == r.ItemList[j].Id {
					rewards[r.ItemList[j].Id] = r.ItemList[j].Num * times
					break
				}
			}
		}
	case REWARD_TYPE_ROLE_PIECES:
		var tempIntList = make([]int32, 0)
		for _, v := range roleList {
			var roleConfig = GetRoleConfig(v)
			if roleConfig == nil {
				continue
			}
			rewards[roleConfig.ConvItem.ItemId] = r.Num
			tempIntList = append(tempIntList, roleConfig.ConvItem.ItemId)
		}

		if r.RandomNum > 0 {
			var maxIndex = 0
			var AddNum = 0
			for AddNum < int(r.RandomNum) {
				var index = tools.MyRand(0, int32(len(rewards))-1)
				rewards[tempIntList[index]] += 1
				if maxIndex > 1000 {
					logger.Error("REWARD_TYPE_ROLE_PIECES failed roleList:%v,r.RandomNum:%v", roleList, r.RandomNum)
					break
				}
				maxIndex++
				AddNum++
			}
		}
	default:
		return nil
	}
	return rewards
}
